import socket 
import time
import threading

# 全局变量：存储接收到的数据（格式：[(客户端地址, 数据), ...]）
received_data = []
# 电梯楼层
floor = [1,2,3]
devList = {
    "escalator":{
        "open":"01050000FF008C3A",
        "close":"010500000000CDCA",
        "down":"020F0000000201021F43",
        "up":"020F0000000201015F42",
        "none":"020F0000000201009E82",
        "1":"0206000000014839",
        "2":"0206000000020838",
        "3":"020600000003C9F8"
    },
    "gates":{
        "open":"01050000FF008C3A",
        "close":"010500000000CDCA",
    }
}

devstate = {
    "escalator":{
        "state":"IDLE",
        "detall":"None",
        "floor":1
    },"gates":{
        "state":"close"
    }
}

def getDevState():
    return devstate


class GatController:
    def __init__(self, ip, port, timeout=5):
        self.ip = ip
        self.port = port
        self.timeout = timeout
        self.socket = None

    def connect(self):
        """建立TCP连接"""
        try:
            self.socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            self.socket.settimeout(self.timeout)
            self.socket.connect((self.ip, self.port))
            print(f"已连接到闸机：{self.ip}:{self.port}")
            return True
        except Exception as e:
            print(f"连接失败：{e}")
            self.socket = None
            return False

    def send_command(self, hex_command):
        """发送十六进制指令"""
        if not self.socket:
            print("未建立连接，请先调用connect()")
            return False
        try:
            # 将十六进制字符串转换为字节流
            command_bytes = bytes.fromhex(hex_command)
            self.socket.sendall(command_bytes)
            print(f"已发送指令：{hex_command}")
            
            # 接收闸机响应（可选，根据闸机是否返回响应调整）
            response = self.socket.recv(1024)
            if response:
                print(f"收到响应：{response.hex().upper()}")
            return True
        except Exception as e:
            print(f"发送失败：{e}")
            return False

    def close(self):
        """关闭连接"""
        if self.socket:
            self.socket.close()
            print("连接已关闭")
        self.socket = None

def handle_client(client_socket, client_address):
    """处理客户端连接，将数据存入全局变量"""
    print(f"新连接来自: {client_address}")
    gates = GatController("192.168.1.108",4242)
    try:
        while True:
            data = client_socket.recv(1024)
            if not data:
                print(f"客户端 {client_address} 断开连接")
                break
            # 解码数据
            decoded_data = data.decode('utf-8')
            print(f"从 {client_address} 收到: {decoded_data}")
            try:
                global devstate 
                if decoded_data == "open\n":
                    if gates.connect():
                        if gates.send_command(devList["gates"]['open']):
                            with threading.Lock():
                                devstate["gates"]["state"] = "open"
                elif decoded_data == "close\n":
                    if gates.connect():
                        if gates.send_command(devList["gates"]['close']):   
                            
                            with threading.Lock():
                                devstate["gates"]["state"] = "close"  
                elif decoded_data == "get\n":
                    print(devstate)
            except Exception as err:
                print(err)
                print("控制闸机失败")
            # 向全局变量添加数据（加锁确保线程安全）
            global received_data
            with threading.Lock():  # 避免多线程同时修改全局变量导致冲突
                received_data.append((client_address, decoded_data))
            
            # 发送确认信息
            response = f"服务器已收到: {decoded_data}"
            client_socket.sendall(response.encode('utf-8'))
    except Exception as e:
        print(f"处理客户端 {client_address} 时出错: {e}")
    finally:
        gates.close()
        client_socket.close()

def server_listen_loop(server_socket):
    """服务器监听循环（子线程中运行）"""
    try:
        while True:
            client_socket, client_address = server_socket.accept()
            client_thread = threading.Thread(
                target=handle_client,
                args=(client_socket, client_address)
            )
            client_thread.daemon = True
            client_thread.start()
    except Exception as e:
        print(f"监听线程出错: {e}")
    finally:
        server_socket.close()
        print("服务器套接字已关闭")["e"]["state"] = "close" 

def start_tcp_servce(host='192.168.1.4', port=8888):
    """启动非阻塞TCP服务器"""
    server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)  # 允许端口复用
    try:
        server_socket.bind((host, port))
        server_socket.listen(5)
        print(f"TCP服务器已启动，监听 {host}:{port} ...")
        listen_thread = threading.Thread(
            target=server_listen_loop,
            args=(server_socket,)
        )
        listen_thread.daemon = True
        listen_thread.start()
        return listen_thread
    
    except Exception as e:
        print(f"服务器启动失败: {e}")
        server_socket.close()
        return None

class linkDev():
    def __init__(self):
        self.escalatorControl = GatController("192.168.1.107",4242)

    def setEscalator(self,state):
        if self.escalatorControl.connect():
            self.escalatorControl.send_command(devList["escalator"][state])
            return True
        return False

    def setGates(self,state):
        if self.gatesControl.connect():
            self.gatesControl.send_command(devList["gates"][state])
            return True
        return False

    def close(self):
        self.gatesControl.close()
        self.escalatorControl.close()
        return True

class Escalator:
    def __init__(self,start_floor=1):
        # 启动tcp服务器
        start_tcp_servce()
        self.escalator_thread = None
        self.start_floor = start_floor
        self.floor_requests = []
        self.dev = linkDev()
        self.running_flag = False

    def openDoor(self):
        if self.dev.setEscalator('open'):
            global devstate 
            with threading.Lock():
                devstate["escalator"]["state"] = "work"
                devstate["escalator"]["detall"] = "open"  
            time.sleep(3)
            print("门已开启")

    def closeDoor(self):
        if self.dev.setEscalator('close'):
            global devstate 
            with threading.Lock():
                devstate["escalator"]["state"] = "work"
                devstate["escalator"]["detall"] = "close"
            time.sleep(3)
            print("门已关闭")

    def setDisplay(self,state):
        if self.dev.setEscalator(state):
            global devstate 
            if state in ["up","down","none"]:
                with threading.Lock():
                    devstate["escalator"]["state"] = "work"
                    devstate["escalator"]["detall"] = state
            else:
                try:
                    with threading.Lock():
                        devstate["escalator"]["state"] = "work"
                        devstate["escalator"]["floor"] = int(state)
                except ValueError as err:
                    print(err)
            time.sleep(1)

    def waitRobot(self):
        time.sleep(5)

    def running(self):
        self.running_flag = True  # 启动时设置为True
        self.setDisplay('1')
        while(self.running_flag):
            try:
                time.sleep(0.5)
                # 获取电梯请求数据
                global received_data
                with threading.Lock():
                    for addr, data in received_data:
                        try:
                            if not int(data) in self.floor_requests:
                                if int(data) in floor:
                                    self.floor_requests.append(int(data))
                                    print(self.floor_requests)
                                    print('已接收到电梯请求数据')
                        except ValueError as err:
                            print(err)
                            # print("未收到请求数据")
                    received_data = []
                # 处理电梯请求
                num = len(self.floor_requests)
                for i in range(num):
                    self.up_floor = self.floor_requests[0]
                    if self.up_floor > self.start_floor:
                        self.setDisplay('up')
                        self.closeDoor()
                    elif self.up_floor < self.start_floor:
                        self.setDisplay('down')
                        self.closeDoor()
                    self.setDisplay('none')
                    self.start_floor = self.up_floor
                    self.setDisplay(str(self.start_floor))
                    self.openDoor()
                    self.waitRobot()
                    self.closeDoor()
                    del self.floor_requests[0]
                global devstate 
                with threading.Lock():
                    devstate["escalator"]["state"] = "IDLE"
                    devstate["escalator"]["detall"] = "none"
            except Exception as err:
                print(err)
        print("电梯控制器线程已退出")

    def start(self):
        try:
            if self.escalator_thread and self.escalator_thread.is_alive():
                print("电梯控制器线程已在运行")
                return self.escalator_thread
            print(f"电梯控制器已打开")
            self.escalator_thread = threading.Thread(
                target=self.running,
                args=(),
                name="EscalatorControllerThread"
            )
            self.escalator_thread.daemon = True
            self.escalator_thread.start()
            return self.escalator_thread
        except Exception as e:
            print(f"电梯控制器启动失败: {e}")
            return None

    def stop(self):
        """停止线程（协作式退出）"""
        if not self.escalator_thread or not self.escalator_thread.is_alive():
            print("电梯控制器线程未在运行")
            return
        # 设置标志位为False，通知线程退出
        self.running_flag = False
        # 等待线程结束（最多等待5秒，避免无限阻塞）
        self.escalator_thread.join(timeout=5)
        if self.escalator_thread.is_alive():
            print("警告：线程未正常退出，可能仍在执行收尾操作")
        else:
            print("电梯控制器已关闭")
            self.escalator_thread = None  # 清空线程对象

if __name__ == "__main__":
    esc = Escalator()
    # 启动电梯控制器
    esc.start()
    while(1):
        time.sleep(1)
        print(getDevState())



    
        
